/****************************************************************************
 * @file    FilterModule.h
 * @brief   Header file for basic data filtering functions.
 * @details This file declares the functions for moving average, median filter,
 *          and average calculation. The functions are implemented as templates
 *          to handle various data types.
 *
 * @author  繁花遁
 * @date    2024-08-30
 ****************************************************************************/

#ifndef FILTERMODULE_H
#define FILTERMODULE_H

#include <QVector>
#include <algorithm>
#include <numeric>

namespace FilterModule {

// Function declarations

/**
 * @brief Computes the moving average of a QVector of data.
 * @param data The input QVector containing data.
 * @param windowSize The size of the moving window.
 * @return A QVector containing the moving average values.
 */
template <typename T>
QVector<T> movingAverage(const QVector<T>& data, int windowSize) {
    QVector<T> result;
    int dataSize = data.size();

    if (windowSize <= 0 || dataSize < windowSize) {
        return result; // Return an empty QVector if invalid windowSize.
    }

    T sum = std::accumulate(data.begin(), data.begin() + windowSize, static_cast<T>(0));
    result.append(sum / windowSize);

    for (int i = windowSize; i < dataSize; ++i) {
        sum += data[i] - data[i - windowSize];
        result.append(sum / windowSize);
    }

    return result;
}

/**
 * @brief Applies a median filter to a QVector of data.
 * @param data The input QVector containing data.
 * @param windowSize The size of the filtering window.
 * @return A QVector containing the median-filtered values.
 */
template <typename T>
QVector<T> medianFilter(const QVector<T>& data, int windowSize) {
    QVector<T> result;
    int dataSize = data.size();

    if (windowSize <= 0 || dataSize < windowSize) {
        return result; // Return an empty QVector if invalid windowSize.
    }

    QVector<T> window;
    for (int i = 0; i <= dataSize - windowSize; ++i) {
        window.clear();
        for (int j = i; j < i + windowSize; ++j) {
            window.append(data[j]);
        }
        std::sort(window.begin(), window.end());
        result.append(window[window.size() / 2]);
    }

    return result;
}

/**
 * @brief Computes the average value of a QVector of data.
 * @param data The input QVector containing data.
 * @return The average value of the data.
 */
template <typename T>
T getAverage(const QVector<T>& data) {
    if (data.isEmpty()) {
        return static_cast<T>(0); // Return 0 if QVector is empty.
    }

    T sum = std::accumulate(data.begin(), data.end(), static_cast<T>(0));
    return sum / data.size();
}

} // namespace FilterModule

#endif // FILTERMODULE_H
